use std::{thread, time};

fn jenkins_hash(key :&[u8], len:usize) ->i64 {
    let mut hash:u128 = 0 ;
    for number in (0..len){
        hash += key[number] as u128;
        let mut temp = hash & 0x003F_FFFF_FFFF_FFFF;
        hash += (temp << 10);
        let mut temp = hash & 0xFFFF_FFFF_FFFF_FFC0;
        hash ^= (temp >> 6);
    };
    hash += (hash << 3);
    hash ^= (hash >> 11);
    hash += (hash << 15);
    // println!("hash 0x{:X} 0x{:X} ", hash , hash as i64);
    return hash as i64;
}

//D-H密码交换
fn is_prime(n: u128) -> bool {
    !(2..(n)).any(|x| n % x == 0)
}
fn max_prime(n: u128) -> u128 {
    let mut num = n;
    while !is_prime(num) {
        num = num - 1;
    }
    num
}
// x^y mod p 如何计算 13^15679 mod 458
fn pow_mod(x: u128, y: u128, p: u128) -> u128 {
    if y == 0 {
        return 1;
    } else {
        let z = pow_mod(x, y / 2, p); //如果y=5_u128, y/2=2
        if y % 2 == 0 {
            return ((z % p) * (z % p)) % p;
        } else {
            return ((((x % p) * (z % p)) % p) * (z % p)) % p;
        }
    }
}

//求p 原始根 的集合,最多产生元根的上限，从小至大
fn generator_primitive_root(p: u128, num: u128) -> Vec<u128> {
    if !is_prime(p) {
        panic!("p:{} is not prime!", p);
    }
    let mut values: Vec<u128> = Vec::new();
    let target = (1..p).map(|x| x).collect::<Vec<u128>>();
    for i in 1..p {
        if values.len() as u128 > num {
            return values;
        }
        let mut temp_value: Vec<u128> = (1..p).map(|y| pow_mod(i, y, p)).collect();
        temp_value.sort();
        if temp_value == target {
            values.push(i);
            //println!("value:{:?}=>{}",temp_value,x);
        }
    }
    println!("元根value:{:?}", values);
    values
}
//求 指数i, 即为b(任意数)的以a为基数的模p的离散对数。
fn dis_log(b: u128, a: u128, p: u128) -> u128 {
    //对于任意数b及素数p的原始根a，可以找到一个唯一的指数i，满足：b=( a ^ i) mod p，其中 0≤i≤p-1
    let data: Vec<u128> = (0..p - 1).filter(|&i| pow_mod(a, i, p) == b).collect();
    println!("dis_log=> i ={:?}", data);
    data[0]
}

fn main() {
    println!("Hello, world!");
    let seed_test1= [0x25, 0x27, 0xf6, 0x85, 0x67, 0x15, 0xad, 0x1d, 0xd2, 0x94, 0xdd, 0xc4, 0x76, 0x19, 0x39, 0x31,
        0xf1, 0xad, 0xb5, 0x58, 0xf0, 0x93, 0x97, 0x32, 0x19, 0x2b, 0xd1, 0xc0, 0xfd, 0x16, 0x8e, 0x4e];
    ;
    let seed_test2= [0x26, 0x27, 0xf6, 0x85, 0x67, 0x15, 0xad, 0x1d, 0xd2, 0x94, 0xdd, 0xc4, 0x76, 0x19, 0x39, 0x31,
        0xf1, 0xad, 0xb5, 0x58, 0x02, 0x93, 0x92, 0x32, 0x19, 0x2b, 0xd1, 0xc0, 0xfd, 0x16, 0x8e, 0x4e];
    ;
    let a_key= crypto::curve25519::curve25519_base(seed_test1.as_ref());
    let b_key= crypto::curve25519::curve25519_base(seed_test2.as_ref());
    let (key_pri_A,key_pub_A)=crypto::ed25519::keypair(a_key.as_ref());
    let (key_pri_B,key_pub_B)=crypto::ed25519::keypair(b_key.as_ref());


    let keyid_a_pri = jenkins_hash(&key_pri_A,key_pri_A.len());
    let keyid_a_pub = jenkins_hash(&key_pub_A,key_pub_A.len());

    let keyid_b_pri = jenkins_hash(&key_pri_B,key_pri_B.len());
    let keyid_b_pub = jenkins_hash(&key_pub_B,key_pub_B.len());

    println!("A pri-{:X} , pub - {:X} " ,keyid_a_pri ,keyid_a_pub  );
    println!("B pri-{:X} , pub - {:X} " ,keyid_b_pri ,keyid_b_pub  );

    println!("\n真实环境中的参数：");
    // 真实中的加密参数
    let g: u128 = 113;
    let p: u128 = 2_u128.pow(64) - 1; //巨大的质数
    let a_private_key = keyid_a_pri as u128 ;// 12583; //保密
    let a_public_key = keyid_a_pub as u128 ;// 12583; //保密
    // 协商
    let a_pri_to_pub_num = pow_mod(g, a_private_key, a_public_key % p);
    let a_pub_to_pri_num = pow_mod(g, a_public_key, a_public_key % p);

    // 发生的
    let a_compute_send_num = pow_mod(a_pri_to_pub_num, a_pri_to_pub_num, p);
    let a_compute_send_2_num = pow_mod(g, a_pub_to_pri_num, p);

    println!("a_compute_send_num {:X} , {:X} " ,a_compute_send_num , a_compute_send_2_num );



    let b_private_key = keyid_b_pri as u128 ; //11258; //保密

crypto::ed25519::exchange();


    let a_send_to_b_num = pow_mod(g, a_private_key, p);
    let b_send_to_a_num = pow_mod(g, b_private_key, p);
    println!("真实环境中的A发送的值：{:X}", a_send_to_b_num);
    println!("真实环境中的B发送的值：{:X}", b_send_to_a_num);
    let a_compute_key_num = pow_mod(b_send_to_a_num, a_private_key, p);
    let b_compute_key_num = pow_mod(a_send_to_b_num, b_private_key, p);
    println!("真实环境中a_compute_key_num:{:X}", a_compute_key_num);
    println!("真实环境中b_compute_key_num:{:X}", b_compute_key_num);

    println!("mod:{}", pow_mod(48_u128, 23_u128, 187));
    let sleep_seconds = time::Duration::from_secs(1000);
    thread::sleep(sleep_seconds);


}
